package com.yoj.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 专门提供RedisLimiter 限流服务的
 */
@Slf4j
@Component
public class RedisLimiterManager {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 限流操作
     * @param key 区分不同的限流器，用户 id 作为唯一标识符
     *            通过此参数可以为不同的对象设置不同的限流策略
     * @return 如果返回true，则表示请求通过限流；如果返回false，则表示请求被限流
     */
    @Deprecated
    public boolean doRateLimit(String key) {
        // 根据 key 获取或创建一个限流器实例
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);

        // 参数1 type：限流类型，总体的限流策略。
        // 参数2 rate：限流速率，即单位时间内允许通过的请求数量
        // 参数3 rateInterval：限流时间间隔，即限流速率的计算周期长度
        // 参数4 unit：限流时间间隔单位，可以是秒、毫秒等。
        // 每秒最多允许1次操作，每5秒最多允许1次操作
        boolean trySetRate = rateLimiter.trySetRate(RateType.OVERALL, 1, 5, RateIntervalUnit.SECONDS);

        // 如果成功设置了限流速率，则记录初始化的速率和时间间隔
        if (trySetRate) {
            log.info("init rate = {}, interval = {}", rateLimiter.getConfig().getRate(), rateLimiter.getConfig().getRateInterval());
        }
        // 每当一个操作来了后，请求一个令牌
        return rateLimiter.tryAcquire(1);
    }

    /**
     * 初始化限流器
     * @param key          限流器的唯一标识（如用户 ID 或接口路径）
     * @param rate         令牌生成速率（每秒生成多少个令牌）
     * @param rateInterval 限流的时间窗口
     * @return 是否允许访问
     */
    public boolean isAllowed(String key, long rate, int rateInterval) {
        // 声明限流器
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        // 设置限流规则：每 rateInterval 秒生成 rate 个令牌
        rateLimiter.trySetRate(RateType.OVERALL, rate, rateInterval, RateIntervalUnit.SECONDS);
        // 尝试获取一个令牌
        return rateLimiter.tryAcquire();
    }
}
